#include <DXUT.h>
#include <SDKmisc.h>
#include <stdexcept>
#include <sstream>

#include "HUD.h"


e3d::HUD::~HUD()
{
	SAFE_RELEASE( m_ndcBuffer );
	SAFE_RELEASE( m_ndcLayout );
	SAFE_RELEASE( m_hudTexRV );

	SAFE_RELEASE( m_font );
	SAFE_RELEASE( m_sprite );

	delete m_healthText;
	delete m_ammoText;
}


e3d::HUD::HUD(ID3D10Device* device, ID3D10Effect* effect )
:	m_ndcBuffer( NULL ), 
	m_ndcLayout( NULL ),
	m_hudTexRV( NULL ),
	m_font( NULL ),
	m_sprite( NULL ),
	m_device( device ),
	m_effect( effect ),
	m_healthText( NULL ),
	m_ammoText( NULL ),
	m_health( L"99"),
	m_ammo(L"99")
{
	//------------------------------------------------
	// Load the hud texture
	//------------------------------------------------
	m_hudTexture = effect->GetVariableByName( "hudTexture" )->AsShaderResource();
	D3DX10CreateShaderResourceViewFromFile( m_device, L"textures/hud_4_to_3.png", NULL, NULL, &m_hudTexRV, NULL );

	if( FAILED( m_hudTexture->SetResource( m_hudTexRV ) ) )
		throw std::logic_error("Cannot set shader resource");
	
	//------------------------------------------------
	// Create vertex buffer for hud
	//------------------------------------------------
	hudVertex ndcBuffer[6] =
	{
		{ D3DXVECTOR4( -1.0f, -0.8f, 0.0f, 1.0f ), D3DXVECTOR2( 0, 0 ) },
		{ D3DXVECTOR4( 1.0f, -0.8f, 0, 1.0f  ), D3DXVECTOR2( 1, 0 ) },
		{ D3DXVECTOR4( -1.0f, -1.0f, 0, 1.0f  ),D3DXVECTOR2( 0, 1 ) },
		{ D3DXVECTOR4( -1.0f, -1.0f, 0, 1.0f  ), D3DXVECTOR2( 0, 1 ) },
		{ D3DXVECTOR4( 1.0f, -0.8f, 0, 1.0f  ), D3DXVECTOR2( 1, 0 ) },
		{ D3DXVECTOR4( 1.0f, -1.0f, 0, 1.0f  ), D3DXVECTOR2( 1, 1 ) }
	};

	D3D10_INPUT_ELEMENT_DESC ndcInputDesc[] = 
	{
		{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D10_APPEND_ALIGNED_ELEMENT, D3D10_INPUT_PER_VERTEX_DATA, 0 },
		{ "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, D3D10_APPEND_ALIGNED_ELEMENT, D3D10_INPUT_PER_VERTEX_DATA, 0 }
	};
	unsigned int numElements = sizeof(ndcInputDesc) / sizeof(ndcInputDesc[0]);

	D3D10_BUFFER_DESC ndcDesc;
	ndcDesc.Usage = D3D10_USAGE_DEFAULT;
	ndcDesc.ByteWidth = sizeof( hudVertex ) * 6;
	ndcDesc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
	ndcDesc.CPUAccessFlags = 0;
	ndcDesc.MiscFlags = 0;
	D3D10_SUBRESOURCE_DATA ndcInitData;
	ndcInitData.pSysMem = ndcBuffer;
	if( FAILED( m_device->CreateBuffer( &ndcDesc, &ndcInitData, &m_ndcBuffer ) ) )
		throw std::logic_error("Could not create input layout");

	ID3D10EffectTechnique* tech = effect->GetTechniqueByName("PhongShading");
	ID3D10EffectPass* cmPass = tech->GetPassByName( "hud" );

	D3D10_PASS_DESC cmPassDesc;
	cmPass->GetDesc( &cmPassDesc );
	if( FAILED( m_device->CreateInputLayout( ndcInputDesc, numElements, cmPassDesc.pIAInputSignature, cmPassDesc.IAInputSignatureSize, &m_ndcLayout)))
		throw std::logic_error("Could not create input layout");

	D3DX10CreateSprite( device, 500, &m_sprite );
}

void e3d::HUD::render( ID3D10EffectTechnique* tech, const D3DXVECTOR3* camPos )
{
	unsigned int stride = sizeof( hudVertex );
	unsigned int offset = 0;

	m_device->IASetInputLayout( m_ndcLayout );
	m_device->IASetVertexBuffers( 0, 1, &m_ndcBuffer, &stride, &offset );
	m_device->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

	tech->GetPassByName("hud")->Apply(0);

	m_device->Draw( 6, 0 );

	m_healthText->Begin();
	// ws: 655
	m_healthText->SetInsertionPos(	static_cast<int>( 605.0 * m_currentScreenWidth / 1680.0 ), 
									static_cast<int>( m_currentScreenHeight - 78 * m_currentScreenHeight / 1050.0 ) );
	m_healthText->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
	m_healthText->DrawFormattedTextLine( m_health.c_str() );
	m_healthText->End();

	m_ammoText->Begin();
	// ws: 890
	m_ammoText->SetInsertionPos(	static_cast<int>( 910.0 * m_currentScreenWidth / 1680.0 ), 
		static_cast<int>( m_currentScreenHeight - 78 * m_currentScreenHeight / 1050.0 ) );
	m_ammoText->SetForegroundColor( D3DXCOLOR( 1.0f, 1.0f, 1.0f, 1.0f ) );
	m_ammoText->DrawFormattedTextLine( m_health.c_str() );
	m_ammoText->End();
}


void e3d::HUD::onResizeSwapChain(ID3D10Device* dev, unsigned int width, unsigned int height)
{
	m_currentScreenWidth = width;
	m_currentScreenHeight = height;

	SAFE_DELETE( m_healthText );
	SAFE_DELETE(  m_ammoText );
	
	SAFE_RELEASE( m_font );
	
	D3DX10CreateFont( dev, static_cast<int>( 50 *  m_currentScreenHeight / 1050.0f ), 0, FW_BOLD, 1, FALSE, DEFAULT_CHARSET,
		OUT_DEVICE_PRECIS, ANTIALIASED_QUALITY, DEFAULT_PITCH | FF_DONTCARE, L"Gentium", &m_font );

	m_healthText = new CDXUTTextHelper( NULL, NULL, m_font, m_sprite, 15 );
	m_ammoText = new CDXUTTextHelper( NULL, NULL, m_font, m_sprite, 15 );
}

void e3d::HUD::setHealth( unsigned int health )
{
	std::wostringstream os;
	os << health;
	m_health = os.str();
}

void e3d::HUD::setAmmo( unsigned int ammo )
{
	std::wostringstream os;
	os << ammo;
	m_ammo = os.str();
}